Contents

总结自:《Thinking in java》

1.创建一个对象引用会初始化为null,使用任何引用前,必须为其指定一个对象;
一种安全的做法是:创建一个引用的同时便进行初始化。

  1. java的对象引用创建在堆栈上。
  2. java中的对象创建在堆上。
  3. 对于基本类型,java采取和c和c++相同的方法,也就是不用new来创建变量,而是创建一个
    并非引用的“自动变量”,这个变量直接存储“值”,并置于堆栈中,因此更加高效
  4. java的char是16位的,最大值为2^16 - 1,最小值为0,为了支持unicode
  5. 基本类型都有包装器类,使得可以在堆上创建一个非基本对象

    1
    2
    3
    4
    5
    6
    例:char c = 'x';
    Character ch = new Character('x');
    也可以自动包装:
    Character ch = 'x';
    也可以反向转换:
    char c = ch;
  6. 在java中,下面这段会报错x已经定义过了。java不允许将较大作用于的变量“隐藏”,
    因为设计者认为这样会导致程序混乱

    1
    2
    3
    4
    5
    6
    {
    int x = 12;
    {
    int x = 96;
    }
    }
  7. java对象不具备和基本类型一样的生命周几,当用new创建一个java对象时,他可以存活
    于作用于之外。

  8. 引用s在作用域终点就消失了,然而s指向的String对象仍继续占据内存空间

    1
    2
    3
    4
    {
    String s = new String("asd");
    }
    s = "123";
  9. 类的某个成员是基本数据类型,即使没有进行初始化,java也会确保他获得一个默认值

    1
    2
    3
    4
    5
    6
    7
    8
    booleanfalse;
    byte: (byte)0
    char: '\u0000'(null)
    int: 0
    long: 0L
    short: (short)0
    float: 0.0f
    double: 0.0d

建议:使用前明确的给它初始化
然而对于“局部变量”(即并非某个类的字段)可能会是任意值

11.类的名字必须和文件名相同。类名用大峰驼,其他用小峰驼。

12.

1
2
3
4
5
6
7
8
9
10
11
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);

System.out.println(n1 == n2);
System.out.println(n1 != n2);

System.out.println(n1.equals(n2));
输出:
False
True
True

用于对象时对象用==和!=时比较的是对象的引用,所以先false再true,要比较两个对象的实际内容是否相同要用equals()方法

13.基本类型直接使用==和!=比较
“==”用于比较引用和比较基本数据类型时具有不同的功能:
   比较基本数据类型,如果两个值相同,则结果为true ,而在比较引用时,如果引用指向内存中的同一对象,结果为true.

1
2
3
4
5
Object下的Eauals原始方法:
public boolean equals(Object obj) {

return (this == obj);
}

14.与c和c++不同的是:在java中不可以将一个非布尔值当作布尔值在逻辑表达式中使用。
int i = 1;
int j = 2;
System.out.println(i && j);
在c和c++中(i && j) 的值为true,i不等于0且j不等于0

15.后缀:
大写或小写:
L : long
F : float
D : double
十六进制数适用于所有整数数据类型,以前缀0x(或0X),后边跟0-9或小写(或大写)的a-f来表示。
类似的八进制用前缀0以及后续的0-7的数组来表示。

16.java中的左移(<<)在低位补0,
Java中的右移(>>):若符号为正,则在高位插入0;若符号为负,则在高位插入1
Java中的无符号右移(>>>)无论正负都在高位插入0
注意java 中没有<<<

17.无符号右移运算符>>> 只是对32位和64位的值有意义,如果是byte或short值他们先被转换为int类型,再进行右移操作,然后被截断,赋值给原来的类型,在这种情况下可能得到的结果是-1

18.

1
2
3
4
5
6
7
8
9
10
11
12
13
int x = 0, y = 1, z = 2;
String s = "x, y, z ";
System.out.println(s + x + y + z);
System.out.println(x + " " + s);
s += "(summed) = ";
System.out.println(s + (x + y + z));
System.out.println("" + x);

输出:
x, y, z 012
0 x, y, z
x, y, z (summed) = 3
0

  • Java的字符串操作符有一些很有趣的行为,如果表达式以一个字符串起头,那么后续所有操作数都必须是字符串型

  • 倒数第二个例子:用括号来控制表达式的赋值顺序,以便int类型的变量在显示之前确实进行了求和操作

  • 最后一个例子,有时会看到这种一个空的String后面跟随+和一个基本类型变量,以此作为不调用更加麻烦的显式方法(例如: Integer.toString())而执行字符串转换的方式

19.java不会自动地将int数值转换成布尔值所以不能像c和c++这么用while(T–),而要改为:while(T—- > 0)

20.如果对基本数据类型执行算数运算或按位运算,大家会发现,只要数据类型比int小(即char,byte,short),那么在运算之前,这些值会自动转换成int,这样一来最终生成的结果就是int类型,如果想把结果赋值给较小的类型,就必须使用类型的转换,可能会有信息丢失

21.java里没有sizeof()

22.注意,能够对布尔型值进行的运算非常有限,我们只能赋给它true和false值,并测试它为真还是假,而不能将布尔值相加,或对布尔值进行其他任何运算

23.带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环,带标签的break会中断并跳出标签所指的循环。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
label1 :
for(int i = 1; i <= 7; i++){
for(int j = 1; j <= 7; j++){
if(i == 2 && j == 2)
continue label1;
if(i == 3 && j == 3)
break label1;
System.out.println("i: " + i + " " + "j: " + j);

}
}
System.out.println("hello world!");

输出:
i: 1 j: 1
i: 1 j: 2
i: 1 j: 3
i: 1 j: 4
i: 1 j: 5
i: 1 j: 6
i: 1 j: 7
i: 2 j: 1
i: 3 j: 1
i: 3 j: 2
hello world!

24.switch语句中:必要时,可在各个case中使用{}来明确产生独立的复合语句。
case 分支可以不使用{},并不是任何情况下case分支都可以不加{},比如你想在某个case里定义一个变量:switch (formWay)
{
case 1 :
 { 
int a=2; //正确,变量a被明确限定在当前{}范围内。

 } 
case 2 :

}

25.在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。

26.不接受任何参数的构造器叫做默认构造器

27.不能根据返回值来区分重载方法

28.如果在方法内部调用同一个类的另一个方法,就不必使用this,直接调用即可。

29.尽管可以用this调用一个构造器,但却不能调用两个,此外必须将构造器调用置于最起始处,否则编译器会报错

30.除构造器之外,编译器禁止在其他任何方法中调用构造器

31.垃圾回收器只知道释放那些经由new分配的内存。

32.初始化顺序:
  静态初始化只有在必要时刻才会进行,如果不创建相应类的对象,或不调用静态方法时,则不会初始化。
先初始化静态对象,在类的内部,变量定义的先后顺序决定了初始化的顺序,即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Window{
Window(int mark) { System.out.println("Window(" + mark + ")");}
}

class Houses{
Window w1 = new Window(1);
Houses(){
System.out.println("House()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f() { System.out.println("f()");}

static{
System.out.println("static{}");
}

static void g(){ //没有调用该静态方法,所以没有初始化它
System.out.println("static void g()");
}
Window w3 = new Window(3);
}

public class lianxix {

public static void main(String[] args)
{

Houses h = new Houses();
h.f();
//System.out.println("hello");
}
}
输出:
static{}
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()

33.编译器不允许指定数组大小
数组的初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int[] a, b;//创建引用数组
Random rand = new Random(47);
a = new int[rand.nextInt(20)];//基本数据类型(int)的数组的元素初始化为0
System.out.println("The length: " + a.length);
System.out.println(Arrays.toString(a));

b = new int[rand.nextInt(20)];
System.out.println("The length: " + b.length);
System.out.println(Arrays.toString(b));

Integer[] c, d;//创建引用数组//引用数组的元素初始化为null
c = new Integer[rand.nextInt(20)];
System.out.println("The length: " + c.length);
System.out.println(Arrays.toString(c));

d = new Integer[rand.nextInt(20)];
System.out.println("The length: " + d.length);
System.out.println(Arrays.toString(d));

34.在编译单元内可以有一个public类,该类的名称必须与文件的名称相同,每个编译单元只能有一个public类

Contents